package lib.quasar.chat;

import android.app.ActivityManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.os.SystemClock;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

import com.google.gson.Gson;

import java.util.List;
import java.util.concurrent.TimeUnit;

import lib.quasar.context.BaseApp;
import lib.quasar.context.BaseConstant;
import lib.quasar.db.manager.DBManager;
import lib.quasar.db.table.Chat;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;

/**
 * description: 消息服务
 * created by kalu on 2018/6/12 14:14
 */
public final class ChatService extends Service {

    private boolean isConn;
    private boolean isInit;

    public final static int TYPE_SUCC = 1000; // 连接成功
    public final static int TYPE_TEST = 1001; // 测试消息
    public final static int TYPE_HANDLER = 1002; // 握手
    public final static int TYPE_HANDLER_SUCC = 1003; // 握手成功
    public final static int TYPE_HANDLER_FAIL = 1004; // 握手失败
    public final static int TYPE_RETRY = 1005; // 重试远程连接
    public final static int TYPE_UNBIND = 1007; // 重试远程连接

    public final static int TYPE_MESSAGE = 1006; // 发送消息

    public final static String MESSAGE_MODEL = "message_model";
    public final static String MESSAGE_CLIENTID = "message_clientid";

    public final static String INTENT_NAME = "lib.quasar.chat.ChatService";
    public final static String INTENT_BOOT = "INTENT_BOOT";
    public final static String INTENT_ALERT = "INTENT_ALERT";
    public final static String INTENT_JOB = "INTENT_JOB";

    private final String MAIN_NAME = "com.quasar.hpatient.module.comm_main.MainActivity";

    private final OkHttpClient socketClient = new OkHttpClient.Builder()
            .connectTimeout(5, TimeUnit.SECONDS)
            .writeTimeout(5, TimeUnit.SECONDS)
            .readTimeout(5, TimeUnit.SECONDS)
            .retryOnConnectionFailure(false) // 设置出现错误进行重新连接。
            .build();

    private final Request socketRequest = new Request.Builder()
            .url(BaseConstant.SOCKET_URL)
            .build();

    @Override
    public void onCreate() {
        Log.e("ChatService", "onCreate ==>");
        super.onCreate();
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.e("ChatService", "onBind ==>");
        return mRemoteMessenger.getBinder();
    }

    private final HandlerThread mHandlerThread = new HandlerThread("HandlerThread");

    {
        mHandlerThread.start();
    }

    //private Messenger remoteMessage = null;

    private final Messenger mRemoteMessenger = new Messenger(new Handler(mHandlerThread.getLooper()) {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case TYPE_SUCC:
                    Log.e("WebSocketService", "onHandler[连接成功] ==> threadName[" + Thread.currentThread().getName() + "]");
                    socketConnect(msg.replyTo);
                    break;
                case TYPE_HANDLER_SUCC:
                    isInit = true;
                    Log.e("WebSocketService", "onHandler[握手成功] ==> threadName[" + Thread.currentThread().getName() + "]");
                    break;
                case TYPE_HANDLER_FAIL:
                    isInit = false;
                    Log.e("WebSocketService", "onHandler[握手失败] ==> threadName[" + Thread.currentThread().getName() + "], 用户主动重新握手");
                    break;
                case TYPE_RETRY:
                    SystemClock.sleep(2000);
                    socketConnect(msg.replyTo);
                    Log.e("WebSocketService", "onHandler[请求重连] ==> threadName[" + Thread.currentThread().getName() + "], 500ms后发送重新连接消息");
                    break;
                case TYPE_UNBIND:
                    isInit = false;
                    break;

            }
        }
    });

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e("ChatService", "onStartCommand ==>");
        // return Service.START_STICKY
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onStart(Intent intent, int startId) {
        Log.e("ChatService", "onStart ==>");
        super.onStart(intent, startId);
    }

    @Override
    public void onRebind(Intent intent) {
        Log.e("ChatService", "onRebind ==>");
        super.onRebind(intent);
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.e("ChatService", "onUnbind ==>");
        return super.onUnbind(intent);
    }

    @Override
    public void onTaskRemoved(Intent rootIntent) {
        Log.e("ChatService", "onTaskRemoved ==>");
        super.onTaskRemoved(rootIntent);
    }

    @Override
    public void onDestroy() {
        Log.e("ChatService", "onDestroy ==>");
        super.onDestroy();
    }



    private final void socketConnect(Messenger mClientMessenger) {

        if (null == mClientMessenger)
            return;

        if (isConn && (!isInit)){
            try{
                String clientId = DBManager.getInstance().syncGetUserModel().getClientid();
                final Message msg = Message.obtain();
                msg.what = TYPE_HANDLER;
                final Bundle bundle = new Bundle();
                bundle.putString(MESSAGE_CLIENTID, clientId);
                msg.setData(bundle);
                mClientMessenger.send(msg);
                Log.e("WebSocketService", "onMessage[握手消息] ==> threadName[" + Thread.currentThread().getName() + "],  message = " );

            }catch (Exception e) {
                Log.e("WebSocketService", "onMessage[发送消息] ==> 发生异常");
                Log.e("WebSocketService", e.getMessage(), e);
            }


            return;

        }



        socketClient.newWebSocket(socketRequest, new WebSocketListener() {
            @Override
            public void onOpen(WebSocket webSocket, Response response) {
                isConn = true;
                Log.e("WebSocketService", "onOpen ==>");
            }

            @Override
            public void onMessage(WebSocket webSocket, String message) {
                isConn = true;
                // Log.e("WebSocketService", "onMessage ==> message = " + message);

                if (message.isEmpty())
                    return;

                try {

                    final ChatModel chatModel = new Gson().fromJson(message, ChatModel.class);

                    // 握手消息
                    if (chatModel.isInit()) {
                        final String client_id = chatModel.getClient_id();
                        DBManager.getInstance().updataUserClientId(client_id);
                        final Message msg = Message.obtain();
                        msg.what = TYPE_HANDLER;
                        final Bundle bundle = new Bundle();
                        bundle.putString(MESSAGE_CLIENTID, client_id);
                        msg.setData(bundle);
                        mClientMessenger.send(msg);
                        Log.e("WebSocketService", "onMessage[握手消息] ==> threadName[" + Thread.currentThread().getName() + "],  message = " + message);
                    }
                    // 普通消息
                    else {

                        final Chat messageModel = chatModel.getDatas();
                        if (null == messageModel)
                            return;
                        DBManager.getInstance().insertChat(messageModel);

                        // 可见状态
                        if (isAppRunning()) {

                            final Message msg = Message.obtain();
                            msg.what = TYPE_MESSAGE;
                            final Bundle bundle = new Bundle();
                            bundle.putSerializable(MESSAGE_MODEL, messageModel);
                            msg.setData(bundle);
                            msg.replyTo = mRemoteMessenger;
                            mClientMessenger.send(msg);
                            Log.e("WebSocketService", "onMessage[普通消息] ==> threadName[" + Thread.currentThread().getName() + "],  message = " + message);
                        }
                        // 后台状态
                        else {
                            Log.e("WebSocketService", "onMessage[通知消息] ==> threadName[" + Thread.currentThread().getName() + "],  message = " + message);
                            notifyMessage(messageModel);
                        }
                    }
                } catch (Exception e) {
                    Log.e("WebSocketService", "onMessage[发送消息] ==> 发生异常");
                    Log.e("WebSocketService", e.getMessage(), e);
                }

//                Observable.interval(0, 100, TimeUnit.MILLISECONDS).subscribe(aLong -> {
//                    final Message testMessage = Message.obtain();
//                    testMessage.what = TYPE_TEST;
//                    final Bundle bundle = new Bundle();
//                    bundle.putString("json", aLong + "");
//                    testMessage.setData(bundle);
//                    mClientMessenger.send(testMessage);
//                    Log.e("WebSocketService", "发送消息 ==> json = " + aLong);
//                }, throwable -> {
//                    Log.e("WebSocketService", "发送消息 ==> 发生异常");
//                    Log.e("WebSocketService", "发送消息 ==> " + throwable.getMessage(), throwable);
//                });
            }

            @Override
            public void onMessage(WebSocket webSocket, ByteString bytes) {
                isConn = true;
                Log.e("WebSocketService", "onMessage ==> bytes = " + bytes);
            }

            @Override
            public void onClosing(WebSocket webSocket, int code, String reason) {
                isConn = false;
                Log.e("WebSocketService", "onClosing ==> code =" + code + ",  reason = " + reason);
            }

            @Override
            public void onClosed(WebSocket webSocket, int code, String reason) {
                isConn = false;
                Log.e("WebSocketService", "onClosed ==> code =" + code + ",  reason = " + reason);
            }

            @Override
            public void onFailure(WebSocket webSocket, Throwable t, Response response) {
                isConn = false;
                try {
                    final Message msg = Message.obtain();
                    msg.what = TYPE_RETRY;
                    msg.replyTo = mClientMessenger;
                    mClientMessenger.send(msg);
                    Log.e("WebSocketService", "onFailure[发送消息] ==> 连接网络服务失败, message = " + t.getMessage());
                } catch (RemoteException e) {
                    Log.e("WebSocketService", "onFailure[发送消息] ==> 连接网络服务失败");
                    Log.e("WebSocketService", e.getMessage(), e);
                }
            }
        });
    }

    private final void notifyMessage(Chat messageModel) {

        try {

            // step1
            final Intent intent = new Intent(BaseApp.getContext(), Class.forName(MAIN_NAME));
            intent.putExtra(ChatService.MESSAGE_MODEL, messageModel);
            final PendingIntent mPendingIntent = PendingIntent.getActivity(BaseApp.getContext(), 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
            // step2
            final NotificationManager mNotificationManager = (NotificationManager) BaseApp.getContext().getSystemService(Context.NOTIFICATION_SERVICE);
            // step3
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                NotificationChannel chan1 = new NotificationChannel("default", "Primary Channel", NotificationManager.IMPORTANCE_DEFAULT);
                chan1.setLightColor(Color.TRANSPARENT);
                chan1.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
                mNotificationManager.createNotificationChannel(chan1);
            }
            final NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(BaseApp.getContext(), Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? "default" : null);
            // step4
            // 图片
            if (Chat.PICTURE.equals(messageModel.getMessage_type())) {
                mBuilder.setContentText("[图片]");
                mBuilder.setTicker("[图片]");
            }
            // 化验单
            else if (Chat.INSPECTION.equals(messageModel.getMessage_type())) {
                mBuilder.setContentText("化验单消息");
                mBuilder.setTicker("化验单消息");
            }
            // 诊断
            else if (Chat.DIAGNOSE.equals(messageModel.getMessage_type())) {
                mBuilder.setContentText("诊断消息");
                mBuilder.setTicker("诊断消息");
            }
            // 化验单
            else if (Chat.INSPECTION.equals(messageModel.getMessage_type())) {
                mBuilder.setContentText("化验单消息");
                mBuilder.setTicker("化验单消息");
            }
            // 文字消息
            else {
                mBuilder.setContentText(messageModel.getMessage());
                mBuilder.setTicker(messageModel.getMessage());
            }

            //设置通知栏点击意图
            mBuilder.setContentTitle(messageModel.getSend_name());
            mBuilder.setContentIntent(mPendingIntent);
            //通知产生的时间，会在通知信息里显示，一般是系统获取到的时间
            mBuilder.setWhen(System.currentTimeMillis());
            //设置该通知优先级
            mBuilder.setPriority(Notification.PRIORITY_MAX);
            //设置这个标志当用户单击面板就可以让通知将自动取消
            mBuilder.setAutoCancel(true);
            //使用当前的用户默认设置
            //.setDefaults(Notification.DEFAULT_VIBRATE)
            mBuilder.setDefaults(Notification.DEFAULT_ALL);
            //设置通知小ICON(应用默认图标)
            mBuilder.setSmallIcon(R.mipmap.ic_launcher);
            mNotificationManager.notify((int) messageModel.getSendid().longValue(), mBuilder.build());

        } catch (Exception e) {
            Log.e("WebSocketService", "notifyMessage[通知消息] ==> 发生失败");
            Log.e("WebSocketService", e.getMessage(), e);
        }
    }

    private final boolean isAppRunning() {

        final ActivityManager am = (ActivityManager) BaseApp.getContext().getSystemService(Context.ACTIVITY_SERVICE);
        final List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);
        boolean running = (!tasks.isEmpty() && tasks.get(0).topActivity.getPackageName().equals(BaseApp.getContext().getPackageName()));
        return running;
    }

    private final void closeSocket() {
        socketClient.dispatcher().cancelAll();
    }
}
